﻿/*
(C)小草莓软件	https://www.xcmsoft.com/
QQ：406675425
Email：406675425@qq.com
*/
#include "stdafx.h"
#include "Hsvcs.h"
#include "HsvcsDlg.h"
#include "afxdialogex.h"
#include "../ConfigLoader/SignalConfigLoader.h"
#include "../ConfigLoader/ParameterConfigLoader.h"
#include "../ConfigLoader/HardwareConfigLoader.h"
#include "../ConfigLoader/AiConverterConfigLoader.h"
#include "../ConfigLoader/LogicConfigLoader.h"
#include "../WorkerThreads/ThreadDef.h"
#include "../Misc/StringUlities.h"
#include "../Misc/FolderUnility.h"
#include "MsgPane.h"
#include "PassWordPane.h"



#ifdef _DEBUG
#define new DEBUG_NEW
#endif


#define		INIT_TIMER_ID				100		// 初始化时钟ID
#define		REFRESH_TIMER_ID			200		// 刷新显示时钟ID
#define		QUIT_TIMER_ID				300		// 退出时钟ID
#define     WORKING_TIMER_ID            400     // 设备运行计时ID
#define     WIDTH_SET                    2       // UI微调

//屏蔽系统按键
LRESULT CALLBACK LowLevelKeyboardPorc(int nCode, WPARAM wParam, LPARAM lParam)
{
	BOOL fEatKeystrole = FALSE;
	if (nCode == HC_ACTION)
	{
		switch (wParam)
		{
		case WM_KEYDOWN:
		case WM_SYSKEYDOWN:
		case WM_KEYUP:
		case WM_SYSKEYUP:
		{
			PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;

			//F1
			if (p->vkCode == VK_F1)
				fEatKeystrole = TRUE;

			//WIN
			if (p->vkCode == VK_LWIN || p->vkCode == VK_RWIN)
				fEatKeystrole = TRUE;

			//TAB + ALT
			if ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0))
				fEatKeystrole = TRUE;

			//Esc + Alt
			if ((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0))
				fEatKeystrole = TRUE;

			//Esc + Ctrl
			if ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0))
				fEatKeystrole = TRUE;

			//Ctrl + Space
			if (((GetKeyState(VK_CONTROL) & 0x8000) != 0) && (p->vkCode == VK_SPACE))
				fEatKeystrole = TRUE;

			//ALT + F1
			if (p->vkCode == VK_F1 && ((p->flags & LLKHF_ALTDOWN) != 0))
				fEatKeystrole = TRUE;

			//ALT + F2
			if (p->vkCode == VK_F2 && ((p->flags & LLKHF_ALTDOWN) != 0))
				fEatKeystrole = TRUE;

			//ALT + F3
			if (p->vkCode == VK_F3 && ((p->flags & LLKHF_ALTDOWN) != 0))
				fEatKeystrole = TRUE;

			//ALT + F4
			if (p->vkCode == VK_F4 && ((p->flags & LLKHF_ALTDOWN) != 0))
				fEatKeystrole = TRUE;

			//if (p->vkCode == 0x51 && ((p->flags & LLKHF_ALTDOWN) != 0))
			//{
			//	int  a = 0;
			//}
		}
		break;
		}
	}
	return(fEatKeystrole ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}

CHsvcsDlg::CHsvcsDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CHsvcsDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	m_bWorkerThreadRuning = FALSE;
	m_bRunning = FALSE;
	m_bAbort = FALSE;
	m_bLock = FALSE;

	m_nCellCtrlCount = 0;
	m_pCellCtrls = NULL;

	m_nBlankCellCount = 0;
	m_pBlankCells = NULL;

	m_pBmpLogo = NULL;
	m_bLogo = FALSE;
}

// 创建字体
// szFontName:输入参数，字体名称
// nFontSize：输入参数，字体大小
// font：输出参数，接收字体
void CHsvcsDlg::CreateFontBy(const CString& szFontName, int nFontSize, CFont& font)
{
	font.DeleteObject();

	LOGFONT lf;
	memset(&lf, 0, sizeof(LOGFONT));
	_tcsncpy_s(lf.lfFaceName, LF_FACESIZE, szFontName, wcslen(szFontName));

	lf.lfHeight = nFontSize;
	font.CreateFontIndirect(&lf);
}

void CHsvcsDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_BUTTON_EXIT, m_btnExit);
	DDX_Control(pDX, IDC_BUTTON_START, m_btnStart);
	DDX_Control(pDX, IDC_BUTTON_STOP, m_btnStop);
	DDX_Control(pDX, IDC_LIST_WORK_MODE, m_workModes);
	DDX_Control(pDX, IDC_STATIC_MODE, m_lblWorkMode);
	DDX_Control(pDX, IDC_STATIC_MACHINE, m_lblMachine);
	DDX_Control(pDX, IDC_LIST_MACHINE, m_machine);
	DDX_Control(pDX, IDC_STATIC_PRESSURE, m_lblPressure);
	DDX_Control(pDX, IDC_LIST_PRESSURE, m_pressure);
	DDX_Control(pDX, IDC_STATIC_SET_VAL, m_lblSetItem);
	DDX_Control(pDX, IDC_LIST_USER_SET, m_listSetItem);
	DDX_Control(pDX, IDC_STATIC_STATUS_LABEL, m_lblSysStatus);
	DDX_Control(pDX, IDC_STATIC_CMD_LABEL, m_lblSysCmd);
	DDX_Control(pDX, IDC_STATIC_RUN_STATUS, m_lblRunStatus);
	DDX_Control(pDX, IDC_BUTTON_OIL, m_btnOil);
}

BEGIN_MESSAGE_MAP(CHsvcsDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()	
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
	ON_WM_TIMER()

	ON_LBN_SELCHANGE(IDC_LIST_WORK_MODE, &CHsvcsDlg::OnLbnSelchangeListWorkMode)
	ON_LBN_SELCHANGE(IDC_LIST_MACHINE, &CHsvcsDlg::OnLbnSelchangeListMachine)
	ON_LBN_SELCHANGE(IDC_LIST_PRESSURE, &CHsvcsDlg::OnLbnSelchangeListPressure)

	ON_MESSAGE(WM_IO_THREAD_MSG, &CHsvcsDlg::OnIoThreadMsg)
	ON_MESSAGE(WM_LOGIC_THREAD_RUNNING, &CHsvcsDlg::OnLogicThreadRunning)
	ON_MESSAGE(WM_RUN_LOGIC_THREAD_MSG, &CHsvcsDlg::OnRunLogicThreadMsg)
	ON_MESSAGE(WM_STOP_LOGIC_THREAD_MSG, &CHsvcsDlg::OnStopLogicThreadMsg)	
	ON_MESSAGE(WM_WORKER_THREAD_STOPPED, &CHsvcsDlg::OnWorkerThreadStopped)		
	ON_MESSAGE(WM_DO_STOP_LOGIC, &CHsvcsDlg::OnDoStopLogic) 
	ON_MESSAGE(WM_UI_ALERT, &CHsvcsDlg::OnUiAlert)
	ON_MESSAGE(WM_LOGIC_THREAD_ABORT_MSG, &CHsvcsDlg::OnLogicThreadAbortMsg)
	ON_MESSAGE(WM_LOGIC_THREAD_DIALOG_MSG, &CHsvcsDlg::OnLogicThreadDialogMsg)

	ON_BN_CLICKED(IDC_BUTTON_START, &CHsvcsDlg::OnClickedButtonStart)
	ON_BN_CLICKED(IDC_BUTTON_STOP, &CHsvcsDlg::OnClickedButtonStop)
	ON_BN_CLICKED(IDC_BUTTON_EXIT, &CHsvcsDlg::OnClickedButtonExit)	
	ON_BN_CLICKED(IDC_BUTTON_OIL, &CHsvcsDlg::OnClickedButtonOil)

	ON_WM_NCHITTEST()
	ON_WM_MOVE()
	ON_MESSAGE(WM_START_WAIT_THREAD, &CHsvcsDlg::OnStartWaitThread)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
END_MESSAGE_MAP()

// 加载LOGO图片
BOOL CHsvcsDlg::LoadLogo()
{
	m_bLogo = FALSE;
	CString szLogoFile = GetNameFolder(L"images") + L"\\" + m_windowParam.titlebar.szLogo;

	m_pBmpLogo = Bitmap::FromFile(szLogoFile);
	if (m_pBmpLogo)
	{
		m_bLogo = (ImageTypeUnknown != m_pBmpLogo->GetType());
	}

	if (!m_bLogo)
	{
		CString szMsg;
		szMsg.Format(L"加载LOGO图片失败！\r\n请检查%s文件是否存在或该文件是否图片文件！", m_windowParam.titlebar.szLogo);
		MessageBox(szMsg, L"加载LOGO", MB_OK | MB_ICONERROR);
		PostQuitMessage(1);
		return FALSE;
	}

	return TRUE;
}

// 设置线程管理器参数
void CHsvcsDlg::SetThreadManagerParams()
{
	m_threadManager.SetMainWnd(GetSafeHwnd());
	m_threadManager.SetDataManager(&m_dataManager);
	m_threadManager.SetFactory(&m_aiConverterFactory, &m_signalObjectFactory, &m_parameterFactory);
	m_threadManager.SetLogicCards(&m_logicCards);
	m_threadManager.SetUiObjectManager(&m_uiObjectManager);
	m_threadManager.SetLogicTimerManager(&m_logicTimerManager);
	m_threadManager.SetLogicCounterManager(&m_logicCounterManager);
	m_threadManager.SetStatusTimeManager(&m_statusTimeManager);
	m_threadManager.SetActionSignalManager(&m_actionSignalManager);
}

void CHsvcsDlg::SetLabelParam(CHmjLabel& label, const LABEL_PARAM& labelParam)
{
	label.SetColors(labelParam.backColor, labelParam.textColor, labelParam.borderColor);
	label.SetFontNameAndSize(labelParam.szFontName, labelParam.nFontSize);
}

void CHsvcsDlg::SetRunStatusLabelParam(CRunStatusLabel& label, const RUN_STATUS_PARAM& labelParam)
{
	label.SetColors(labelParam.waitBackColor, labelParam.waitTextColor, 
		labelParam.runBackColor, labelParam.runTextColor, 
		labelParam.stopBackColor, labelParam.stopTextColor,
		labelParam.borderColor);
	label.SetFontNameAndSize(labelParam.szFontName, labelParam.nFontSize);
	label.SetMsg(labelParam.szWaitMsgText, labelParam.szRunMsgText, labelParam.szStopMsgText);
}

void CHsvcsDlg::SetListBox(CHmjLabel& label, const LABEL_PARAM& labelParam, CHmjListBox& listBox, const LISTBOX_PARAM& listParam)
{
	SetLabelParam(label, labelParam);

	listBox.SetItemHeight(listParam.nItemHeight);
	listBox.SetColors(listParam.backColor, listParam.textColor, listParam.selectedBackColor, listParam.selectedTextColor, listParam.borderColor);
	listBox.SetFontNameAndSize(listParam.szFontName, listParam.nFontSize);
}

void CHsvcsDlg::SetButtonParam(CHmjButton& button, const BUTTON_PARAM& buttonParam)
{
	button.SetFontNameAndSize(buttonParam.szFontName, buttonParam.nFontSize);
	button.SetColors(buttonParam.backColor, buttonParam.textColor,
		buttonParam.disableBackColor, buttonParam.disableTextColor,
		buttonParam.borderColor);
}

// 设置UI控件参数
void CHsvcsDlg::SetUiCtrlParams()
{
	// 工作模式
	SetListBox(m_lblWorkMode, m_windowParam.selectPane.workModeLabel, m_workModes, m_windowParam.selectPane.workModeLList);
	// 机型选择
	SetListBox(m_lblMachine, m_windowParam.selectPane.machineLabel, m_machine, m_windowParam.selectPane.machineList);
	// 调压选择
	SetListBox(m_lblPressure, m_windowParam.selectPane.pressureLabel, m_pressure, m_windowParam.selectPane.pressureList);
	// 设定项
	SetListBox(m_lblSetItem, m_windowParam.selectPane.setItemLabel, m_listSetItem, m_windowParam.selectPane.setItemList);
	// 系统状态标签
	SetLabelParam(m_lblSysStatus, m_windowParam.sysStatus.sysStatusLabel);
	// 系统命令标签
	SetLabelParam(m_lblSysCmd, m_windowParam.sysCmd.sysCmdLabel);
	// 启动按钮
	SetButtonParam(m_btnStart, m_windowParam.sysCmd.button);
	// 停止按钮
	SetButtonParam(m_btnStop, m_windowParam.sysCmd.button);
	// 关闭按钮
	SetButtonParam(m_btnExit, m_windowParam.sysCmd.button);
	// 油压检测
	SetButtonParam(m_btnOil, m_windowParam.sysCmd.button);
	// 运行状态标签
	SetRunStatusLabelParam(m_lblRunStatus, m_windowParam.sysCmd.runStatus);
}

BOOL CHsvcsDlg::OnInitDialog()
{	
	CDialogEx::OnInitDialog();
	CWaitCursor waitCursor;

	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	m_btnStart.SetLabel(L"启动设备");
	m_btnStop.SetLabel(L"停止设备");
	m_btnExit.SetLabel(L"关闭设备");
	m_btnOil.SetLabel(L"油压检测");

	// 加载窗口参数
	if (!GetWindowParams())
	{
		PostQuitMessage(1);
		return FALSE;
	}

	// 加载LOGO图片
	if (!LoadLogo())
		return FALSE;

	// 设置UI控件参数
	SetUiCtrlParams();

	// 设置线程管理器参数
	SetThreadManagerParams();

	// 初始化状态标识
	m_bWorkerThreadRuning = FALSE;
	m_bRunning = FALSE;
		
	// 初始化调压选择列表框
	m_pressure.InsertString(-1, L"手动调压");
	m_pressure.InsertString(-1, L"自动调压");
	m_pressure.SetCurSel(-1);

	// ABORT面板
	m_paneAbort.Create(IDD_DIALOG_ABORT, this);

	// 调整窗口大小
	CRect rcWin(0, 0, m_windowParam.nWidth, m_windowParam.nHeight);
	MoveWindow(&rcWin);
	CenterWindow();

	// 初始化时钟
	SetTimer(INIT_TIMER_ID, 50, NULL);	

	//初始化钩子，拦截系统快捷键
	HINSTANCE hins = AfxGetInstanceHandle();
	SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)LowLevelKeyboardPorc, hins, 0);

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

// 初始化时钟处理函数
BOOL CHsvcsDlg::CheckAndInit()
{
	CString szErrMsg;

	CWaitCursor waitCursor;

	m_btnStart.EnableWindow(FALSE);
	m_btnStop.EnableWindow(FALSE);

	// 初始化
	if (!Init())
		return FALSE;

	// 启动I/O线程
	if (!m_threadManager.StartIoThread(szErrMsg))
	{
		MessageBox(szErrMsg, L"启动I/O线程", MB_OK | MB_ICONERROR);
		return FALSE;
	}

	m_bWorkerThreadRuning = TRUE;

	// 更新UI显示
	RefreshUI();

	// 启动更新显示的时钟
	SetTimer(REFRESH_TIMER_ID, 50, NULL);

	// 启动待机逻辑
	if (!StartWaitLogic())
	{
		return FALSE;
	}

	return TRUE;
}

// 绘制标题栏
void CHsvcsDlg::DrawTitleBar(CDC* pDC)
{
	CRect rcClient;
	GetClientRect(&rcClient);

	// 背景
	pDC->FillSolidRect(&rcClient, m_windowParam.borderColor);

	// 标题栏背景
	int nSpace = m_windowParam.nBorderWidth;
	rcClient.InflateRect(-nSpace, -nSpace);

	CRect rcTitle = rcClient;
	rcTitle.bottom = rcTitle.top + m_windowParam.titlebar.nHeight;

	pDC->FillSolidRect(&rcTitle, m_windowParam.titlebar.backColor);

	// LOGO
	int nLogoWidth = 0;
	if (m_bLogo)
	{
		Graphics graphics(pDC->GetSafeHdc());
		double dblK = m_pBmpLogo->GetWidth();
		dblK = dblK / m_pBmpLogo->GetHeight();
		nLogoWidth = (int)(m_windowParam.titlebar.nHeight * dblK);
		graphics.DrawImage(m_pBmpLogo, nSpace, nSpace, nLogoWidth, m_windowParam.titlebar.nHeight);
	}

	// 公司名称
	CRect rcCompany = rcTitle;
	rcCompany.bottom -= m_windowParam.titlebar.companyTextParam.nBottomSpace;
	CRect rcCompany0(0, 0, 2, 2);
	pDC->SetTextColor(m_windowParam.titlebar.companyTextParam.textColor);
	pDC->SetBkColor(m_windowParam.titlebar.companyTextParam.backColor);
	CFont fontCompanyName;
	CreateFontBy(m_windowParam.titlebar.companyTextParam.szFontName, m_windowParam.titlebar.companyTextParam.nFontSize, fontCompanyName);
	CFont* pOldFont = pDC->SelectObject(&fontCompanyName);
	pDC->DrawText(m_windowParam.titlebar.companyTextParam.szText, &rcCompany0, DT_SINGLELINE | DT_CALCRECT);
	pDC->DrawText(m_windowParam.titlebar.companyTextParam.szText, &rcCompany, DT_SINGLELINE | DT_RIGHT | DT_BOTTOM);
	pDC->SelectObject(pOldFont);
	fontCompanyName.DeleteObject();

	// 设备名称
	CString szDeviceName = m_windowParam.titlebar.deviceTextParam.szText;
#ifdef  _FAKE_CARD_
	szDeviceName += L"(调试版)";
#endif
	pDC->SetTextColor(m_windowParam.titlebar.deviceTextParam.textColor);
	pDC->SetBkColor(m_windowParam.titlebar.deviceTextParam.backColor);
	CFont fontDeviceName;
	CreateFontBy(m_windowParam.titlebar.deviceTextParam.szFontName, m_windowParam.titlebar.deviceTextParam.nFontSize, fontDeviceName);
	pOldFont = pDC->SelectObject(&fontDeviceName);
	pDC->DrawText(szDeviceName, &rcTitle, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
	pDC->SelectObject(pOldFont);
	fontDeviceName.DeleteObject();
}

CString ReadHeg()
{
	HKEY hKey = nullptr;
	DWORD dwTpye = REG_SZ;
	DWORD dwValue = sizeof(DWORD);
	LONG lRet = 0;
	RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SoftWare\\Microsoft\\Windows\\CurrentVersion"), 0, KEY_ALL_ACCESS, &hKey);
	TCHAR szValue[1024] = { 0 };
	if (ERROR_SUCCESS != (lRet = RegQueryValueEx(hKey, TEXT("HsvcsExitState"), 0, &dwTpye, (LPBYTE)szValue, &dwValue)))
	{
		return L"";
	}

	CString str;
	str.Format(TEXT("%s"), szValue);
	return str;
}

int SetHsvcsExitState(bool bAutoRun)
{
	//_T宏可以把一个引号引起来的字符串，根你的环境设置，使得编译器会根据编译目标环境选择合适的（Unicode还是ANSI）字符处理方式
	LPCTSTR lpSubKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion");
	HKEY hKey;
	REGSAM flag = KEY_WOW64_64KEY;//当前系统为win7 64位，访问的是64位的注册表，如果访问32位，则改为KEY_WOW64_32KEY
	LONG lRet = RegOpenKeyEx(HKEY_CURRENT_USER, lpSubKey, 0, KEY_ALL_ACCESS | flag, &hKey);
	if (ERROR_SUCCESS != lRet)
	{
		return 0;
	}
	wchar_t szFileName[MAX_PATH] = { 1 };
	LPCTSTR pchrName = L"0";;
	if (bAutoRun)
	{
		pchrName = L"1";;
		lRet = RegSetValueEx(hKey, TEXT("HsvcsExitState"), 0, REG_SZ, (LPBYTE)pchrName, wcslen(pchrName) * sizeof(TCHAR) + 1);
	}
	else
	{
		pchrName = L"0";
		lRet = RegSetValueEx(hKey, TEXT("HsvcsExitState"), 0, REG_SZ, (LPBYTE)pchrName, wcslen(pchrName) * sizeof(TCHAR) + 1);
	}
	if (ERROR_SUCCESS != lRet)
	{
		return 0;
	}
	RegCloseKey(hKey);
	return 1;
}

int SetHsvcsAutoRun(bool bAutoRun)
{
	SetHsvcsExitState(bAutoRun);
	//_T宏可以把一个引号引起来的字符串，根你的环境设置，使得编译器会根据编译目标环境选择合适的（Unicode还是ANSI）字符处理方式
	LPCTSTR lpSubKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
	HKEY hKey;
	REGSAM flag = KEY_WOW64_64KEY;//当前系统为win7 64位，访问的是64位的注册表，如果访问32位，则改为KEY_WOW64_32KEY
	LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_ALL_ACCESS | flag, &hKey);
	if (ERROR_SUCCESS != lRet)
	{
		return 0;
	}
	wchar_t szFileName[MAX_PATH] = { 0 };
	DWORD dwRet = GetModuleFileName(NULL, szFileName, MAX_PATH);
	LPCTSTR pchrName = szFileName;
	if (bAutoRun)
	{
		lRet = RegSetValueEx(hKey, TEXT("Hsvcs"), 0, REG_SZ, (LPBYTE)pchrName, wcslen(pchrName) * sizeof(TCHAR) + 1);	
	}
	else
	{
		lRet = RegDeleteValue(hKey, TEXT("Hsvcs"));
	}
	if (ERROR_SUCCESS != lRet)
	{
		return 0;
	}
	RegCloseKey(hKey);
	return 1;
}

void CHsvcsDlg::OnTimer(UINT_PTR nIDEvent)
{
	if (nIDEvent == INIT_TIMER_ID)
	{
		KillTimer(INIT_TIMER_ID);
		CheckAndInit();
	}
	else if (nIDEvent == REFRESH_TIMER_ID)
	{
		RefreshUI();
	}
	else if (nIDEvent == QUIT_TIMER_ID)
	{
		OnQuitTimer();
	}
	else if (nIDEvent == WORKING_TIMER_ID)	//设备运行时，在“当前工作时间”更新时间
	{
		CTimeSpan span = CTime::GetCurrentTime() - m_workStartTimer;
		CString str_span;
		str_span.Format(L"%d:%d:%d", span.GetHours(), span.GetMinutes(), span.GetSeconds());
		m_cellCurWorkTime.SetValue(str_span);
	}
	else if (nIDEvent == 119)
	{
		KillTimer(119);
		CPassWordPane pane(this);
		pane.DoModal();
		/*
		5.1在界面上通过“ctrl+alt+shift+鼠标左键”组合键弹出锁屏输入框输入“suoping”：既锁屏后主板上电直接进入工程界面，此时界面的关闭设备就是退出系统。
		*/
		if (pane.GetPassWord() == L"suoping")
		{
			SetHsvcsAutoRun(true);
		}

		/*
		5.2在界面上通过“ctrl+alt+shift+鼠标左键”组合键弹出解屏输入框输入“jieping”：既解屏后主板上电直接进入windows下，此时界面的关闭设备就是退出软件。
		*/
		if (pane.GetPassWord() == L"jieping")
		{
			SetHsvcsAutoRun(false);
		}
	}

	CDialogEx::OnTimer(nIDEvent);
}

// 初始化
BOOL CHsvcsDlg::Init()
{
	// 加载信号
	if (!LoadSignals())
		return FALSE;

	// 加载参数
	if (!LoadParameters())
		return FALSE;

	// 加载界面控件
	if (!LoadUiCtrls())
		return FALSE;

	// 加载工作模式
	if (!LoadWorkMode())
		return FALSE;

	// 初始化工作时间信息
	if (!InitWorkTime())
		return FALSE;

	// 刷新显示
	Invalidate();

	// 默认选择
	m_workModes.SetCurSel(0);
	OnLbnSelchangeListWorkMode();
	m_machine.SetCurSel(0);
	OnLbnSelchangeListMachine();
	m_pressure.SetCurSel(0);
	OnLbnSelchangeListPressure();

	return TRUE;
}

// 加载信号
BOOL CHsvcsDlg::LoadSignals()
{
	CString szErrMsg;
	
	CAiConverterConfigLoader aiConverterConfigLoader;
	if (!aiConverterConfigLoader.LoadAiConverters(m_aiConverterFactory, szErrMsg))
	{
		MessageBox(szErrMsg, L"加载AI转换器", MB_OK | MB_ICONERROR);
		return FALSE;
	}
			
	CSignalConfigLoader  signalConfigLoader;
	if (!signalConfigLoader.LoadSignals(m_aiConverterFactory, m_signalObjectFactory, szErrMsg))
	{
		MessageBox(szErrMsg, L"加载信号", MB_OK | MB_ICONERROR);
		return FALSE;
	}
		
	CHardwareConfigLoader hardwareConfigLoader;
	BOOL bRet = hardwareConfigLoader.LoadCards(&m_signalObjectFactory, m_logicCards, szErrMsg);
	if (!bRet)
	{
		MessageBox(szErrMsg, L"加载板卡", MB_OK | MB_ICONERROR);
		return FALSE;
	}

	return TRUE;
}

// 加载参数
BOOL CHsvcsDlg::LoadParameters()
{
	CString szErrMsg;
	CParameterConfigLoader  loader;

	if(!loader.LoadParams(m_parameterFactory, szErrMsg))
	{
		MessageBox(szErrMsg, L"加载配置参数", MB_OK | MB_ICONERROR);
		return FALSE;
	}

	return TRUE;
}

// 加载界面控件
BOOL CHsvcsDlg::LoadUiCtrls()
{		
	CList<CString> userSetItems;
	CString szErrMsg;
	CParameterConfigLoader  loader;

	// 加载配置
	if (!loader.LoadUiCtrls(m_uiSignalFactory, userSetItems, szErrMsg))
	{
		MessageBox(szErrMsg, L"加载界面控件元素", MB_OK | MB_ICONERROR);
		return FALSE;
	}
	
	// 输入信号
	m_nCellCtrlCount = m_uiSignalFactory.GetUiSignalCount();
	m_pCellCtrls = new CHmjCell[m_nCellCtrlCount];
	for (SHORT i = 0; i < m_nCellCtrlCount; i++)
	{
		CHmjCell& cell = m_pCellCtrls[i];

		CUiSignal* pUiSignal = m_uiSignalFactory.GetUiSignal(i);
		cell.SetIdAndUnit(pUiSignal->GetId(), pUiSignal->GetUnit());
		cell.SetNormalMsg(pUiSignal->GetNormalMsg());
		cell.SetSpecialMsg(pUiSignal->GetSpecialMsg());
		for (SHORT j = 0; j < STATE_MAX_LENGTH; j++)
			cell.SetStateMsg(pUiSignal->GetStateMsg(j), j);

		m_uiObjectManager.SetUiCtrl(cell.GetId(), i);
	}
	
	// 用户设定项	
	POSITION pos = userSetItems.GetHeadPosition();
	while (pos)
	{
		const CString szItemId = userSetItems.GetNext(pos);
		m_uiObjectManager.AddUserSetItem(szItemId);
		m_listSetItem.AddString(szItemId);
	}

	// 主窗口句柄
	m_uiObjectManager.SetMainWindow(GetSafeHwnd());

	// 界面布局
	SetUiLayout();
	Invalidate();

	return TRUE;
}

// 加载工作模式
BOOL CHsvcsDlg::LoadWorkMode()
{	
	CString szErrMsg;
	CParameterConfigLoader  loader;

	if (!loader.LoadWorkModes(m_workModeFactory, szErrMsg))
	{
		MessageBox(szErrMsg, L"加载工作模式", MB_OK | MB_ICONERROR);
		return FALSE;
	}

	int nCount = m_workModeFactory.GetWorkModeCount();
	for (int i = 0; i < nCount; i++)
	{
		CWorkMode* pWorkMode = m_workModeFactory.GetWorkMode(i);
		LPCWSTR szIdText = (LPCWSTR)pWorkMode->GetId();
		m_workModes.InsertString(-1, szIdText);
	}

	return TRUE;
}

// 初始化工作时间信息
BOOL CHsvcsDlg::InitWorkTime()
{
	m_cellCurWorkTime.SetIdAndUnit(L"当前工作时间", L"");
	m_cellTotalWorkTime.SetIdAndUnit(L"全部工作时间", L"");

	CString szErrMsg;
	CParameterConfigLoader  loader;

	if (!loader.GetTotalWorkTime(m_totalWorkTime, szErrMsg))
	{
		MessageBox(szErrMsg, L"加载工作时间", MB_OK | MB_ICONERROR);
		return FALSE;
	}

	CString szTotalWorkTime;
	szTotalWorkTime.Format(L"%d小时%d分钟", m_totalWorkTime.nHour, m_totalWorkTime.nMinute);	
	m_cellTotalWorkTime.SetValue(szTotalWorkTime);

	return TRUE;
}

// 加载窗口参数
BOOL CHsvcsDlg::GetWindowParams()
{
	CString szErrMsg;
	CParameterConfigLoader  loader;

	if (!loader.LoadWindowParams(m_windowParam, szErrMsg))
	{
		MessageBox(szErrMsg, L"加载窗口参数", MB_OK | MB_ICONERROR);
		return FALSE;
	}

	return TRUE;
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CHsvcsDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

// 退出时钟的处理函数
void CHsvcsDlg::OnQuitTimer()
{
	if (!m_bWorkerThreadRuning)
	{
		KillTimer(QUIT_TIMER_ID);
		OnOK();
	}
}

void CHsvcsDlg::OnSize(UINT nType, int cx, int cy)
{
	
}

void CHsvcsDlg::OnPaint()
{
	CPaintDC dc(this);
	CRect rcWnd(dc.m_ps.rcPaint);

	CMemDC  dcMem(dc, rcWnd);
	CDC* pDC = &dcMem.GetDC();

	// 绘制标题栏
	DrawTitleBar(pDC);
	// 画工作模式列表框的边框
	DrawListCtrlBorder(pDC, &m_workModes, m_windowParam.selectPane.workModeLList.borderColor);
	// 画机型列表框的边框
	DrawListCtrlBorder(pDC, &m_machine, m_windowParam.selectPane.machineList.borderColor);
	// 画调压选择列表框的边框
	DrawListCtrlBorder(pDC, &m_pressure, m_windowParam.selectPane.pressureList.borderColor);
	// 画设定项列表框的边框
	DrawListCtrlBorder(pDC, &m_listSetItem, m_windowParam.selectPane.setItemList.borderColor);
}

// 画工作模式列表框的边框
void CHsvcsDlg::DrawListCtrlBorder(CDC* pDC, CHmjListBox* pListBox, COLORREF borderColor)
{
	CRect rcCtrl;
	pListBox->GetWindowRect(&rcCtrl);
	ScreenToClient(&rcCtrl);
	rcCtrl.InflateRect(1, 1);
	rcCtrl.right -= 1;
	CPen pen(PS_SOLID, 1, borderColor);
	CPen* pOldPen = pDC->SelectObject(&pen);
	CPoint pts[5];
	pts[0] = CPoint(rcCtrl.left, rcCtrl.top);
	pts[1] = CPoint(rcCtrl.right, rcCtrl.top);
	pts[2] = CPoint(rcCtrl.right, rcCtrl.bottom);
	pts[3] = CPoint(rcCtrl.left, rcCtrl.bottom);
	pts[4] = CPoint(rcCtrl.left, rcCtrl.top);
	pDC->Polyline(pts, 5);
	pDC->SelectObject(pOldPen);
}

// 设置界面布局
void CHsvcsDlg::SetUiLayout()
{
	if (NULL == m_btnStart.GetSafeHwnd())
		return;

	CRect rcClient;
	GetClientRect(&rcClient);
	rcClient.InflateRect(-m_windowParam.nBorderWidth, -m_windowParam.nBorderWidth);	
	rcClient.top = m_windowParam.nBorderWidth + m_windowParam.titlebar.nHeight + m_windowParam.nBorderWidth;

	// 设置右侧面板布局
	CRect rcRightPane = rcClient;
	rcRightPane.left = rcClient.right - m_windowParam.selectPane.nWidth;
	rcRightPane.bottom = rcRightPane.bottom - m_windowParam.sysCmd.button.nHeight - m_windowParam.sysCmd.sysCmdLabel.nHeight;

	SetRightPaneLayout(rcRightPane);
	
	// 设置系统命令布局
	CRect rcSysCmd = rcClient;
	rcSysCmd.top = rcSysCmd.bottom - m_windowParam.sysCmd.button.nHeight - m_windowParam.sysCmd.sysCmdLabel.nHeight;
	//rcSysCmd.right = rcRightPane.left - m_windowParam.nBorderWidth;
	rcSysCmd.right = rcClient.right;

	SetSysCmdLayout(rcSysCmd);

	// 系统状态布局
	rcSysCmd.right = rcRightPane.left - m_windowParam.nBorderWidth;
	CRect rcSysStatus = rcClient;
	rcSysStatus.right = rcSysCmd.right;
	rcSysStatus.bottom = rcSysCmd.top - m_windowParam.nBorderWidth;
	SetSysStatusLayout(rcSysStatus);
}

// 系统状态布局
// rcSysStatus：输入参数，系统命令的位置
void CHsvcsDlg::SetSysStatusLayout(const CRect& rcSysStatus)
{
	CRect rcLabel;

	// 系统状态标签
	rcLabel = rcSysStatus;
	rcLabel.bottom = rcLabel.top + m_windowParam.sysStatus.sysStatusLabel.nHeight;
	m_lblSysStatus.MoveWindow(&rcLabel);

	// 单元格
	CRect rcCell;
	for (SHORT i = 0; i < m_nCellCtrlCount; i++)
	{
		CHmjCell& cell = m_pCellCtrls[i];
		cell.SetCellParam(m_windowParam.sysStatus.gridParam.cellParam);

		// 创建控件
		rcCell = GetCellCtrlPos(rcSysStatus, i);		
		cell.Create(_T(""), WS_CHILD | WS_VISIBLE, rcCell, this);
	}

	// 当前工作时间控件
	m_cellCurWorkTime.SetCellParam(m_windowParam.sysStatus.gridParam.cellParam);
	rcCell = GetCellCtrlPos(rcSysStatus, m_nCellCtrlCount);
	m_cellCurWorkTime.Create(_T(""), WS_CHILD | WS_VISIBLE, rcCell, this);
	// 全部工作时间控件
	m_cellTotalWorkTime.SetCellParam(m_windowParam.sysStatus.gridParam.cellParam);
	rcCell = GetCellCtrlPos(rcSysStatus, m_nCellCtrlCount + 1);
	m_cellTotalWorkTime.Create(_T(""), WS_CHILD | WS_VISIBLE, rcCell, this);

	// 填充空白区域
	int nCellCountPerRow = m_windowParam.sysStatus.gridParam.nCellCountPerRow;
	int nRowCount = GetGridRowCount();
	m_nBlankCellCount = nRowCount * nCellCountPerRow - m_nCellCtrlCount - 2;

	if (m_nBlankCellCount > 0)
	{
		m_pBlankCells = new CHmjCell[m_nBlankCellCount];
		for (SHORT i = 0; i < m_nBlankCellCount; i++)
		{
			CHmjCell& cell = m_pBlankCells[i];
			cell.SetValue(L"");
			cell.SetCellParam(m_windowParam.sysStatus.gridParam.cellParam);

			// 创建控件
			rcCell = GetCellCtrlPos(rcSysStatus, m_nCellCtrlCount + 2 + i);
			cell.Create(_T(""), WS_CHILD | WS_VISIBLE, rcCell, this);
		}
	}
}

// 计算网格位置
// rcSysStatus：输入参数，系统命令的位置
// nIndex：输入参数，网格索引
CRect CHsvcsDlg::GetCellCtrlPos(const CRect& rcSysStatus, int nIndex)
{
	CRect rcLabel;
	rcLabel = rcSysStatus;
	rcLabel.bottom = rcLabel.top + m_windowParam.sysStatus.sysStatusLabel.nHeight;

	int nSpace = 1;
	int nCellCountPerRow = m_windowParam.sysStatus.gridParam.nCellCountPerRow;
	int nRowCount = GetGridRowCount();
	
	int nTotalHeight = rcSysStatus.bottom - rcLabel.bottom;
	int nBlockHeight = nTotalHeight / nRowCount;
	int nCellHeight = nBlockHeight - 2 * nSpace;
	
	int nBlockWidth = rcSysStatus.Width() / nCellCountPerRow;

	int nStartY = rcLabel.bottom + (nTotalHeight - nRowCount * nBlockHeight) / 2 + 1;

	int nRow = (nIndex / nCellCountPerRow);
	int nCol = (nIndex % nCellCountPerRow);
	int x1 = rcSysStatus.left + nCol * nBlockWidth;
	int y1 = nStartY + nRow * nBlockHeight + nSpace;
	int x2 = x1 + nBlockWidth;
	int y2 = y1 + nCellHeight;

	if (nCol == nCellCountPerRow - 1)
	{
		x1 += nSpace;
		x2 = rcSysStatus.right;
	}
	else if (nCol == 0)
	{
		x2 -= nSpace;
	}
	else
	{
		x1 += nSpace;
		x2 -= nSpace;
	}

	CRect rcCell(x1, y1, x2, y2);	

	return rcCell;
}

// 返回网格的行数
int CHsvcsDlg::GetGridRowCount()
{
	int nCellCountPerRow = m_windowParam.sysStatus.gridParam.nCellCountPerRow;

	int nCtrlCount = m_nCellCtrlCount + 2;
	int nRowCount = nCtrlCount / nCellCountPerRow;
	if (nCtrlCount % nCellCountPerRow)
		nRowCount++;
	nRowCount = m_windowParam.sysStatus.gridParam.nCellCountPerLien;
	return nRowCount;
}

// 设置系统命令布局
// rcSysCmd：输入参数，系统命令的位置
void CHsvcsDlg::SetSysCmdLayout(const CRect& rcSysCmd)
{
	CRect rcButton;
	int nButtonWidth = (rcSysCmd.Width() - m_windowParam.selectPane.nWidth) / 5;
	
	// 启动设备按钮
	rcButton = rcSysCmd;
	rcButton.top = rcButton.bottom - m_windowParam.sysCmd.button.nHeight;
	rcButton.right = rcButton.left + nButtonWidth - WIDTH_SET;
	m_btnStart.MoveWindow(&rcButton);

	// 停止设备按钮
	rcButton.MoveToX(rcButton.right);
	rcButton.left += WIDTH_SET;
	rcButton.right += WIDTH_SET;
	m_btnStop.MoveWindow(&rcButton);

	// 关闭设备按钮
	rcButton.MoveToX(rcButton.right);
	rcButton.left += WIDTH_SET;
	rcButton.right += WIDTH_SET;
	m_btnExit.MoveWindow(&rcButton);

	// 油压检测按钮
	if (m_windowParam.bDetectionSwitch)
	{
		rcButton.MoveToX(rcButton.right);
		rcButton.left += WIDTH_SET;
		rcButton.right += WIDTH_SET;
		m_btnOil.MoveWindow(&rcButton);
	}

	// 运行状态标签
	rcButton.MoveToX(rcButton.right);
	rcButton.left += WIDTH_SET;
	rcButton.right = rcSysCmd.right;
	m_lblRunStatus.MoveWindow(&rcButton);

	// 系统命令标签
	rcButton = rcSysCmd;
	rcButton.bottom = rcButton.top + m_windowParam.sysCmd.sysCmdLabel.nHeight;
	m_lblSysCmd.MoveWindow(&rcButton);
}
// 设置右侧面板布局
// rcRightPane：输入参数，右侧面板的位置
void CHsvcsDlg::SetRightPaneLayout(const CRect& rcRightPane)
{
	int left = rcRightPane.left;
	int right = rcRightPane.right;
	int top = rcRightPane.top;
	int bottom = rcRightPane.bottom;
	int h = bottom - top + 1;

	BOOL setItem_isShown = m_listSetItem.GetCount() > 0;	//是否显示设定项
	int h_work_lbl, h_work;
	int h_machine_lbl, h_machine;
	int h_pressure_lbl, h_pressure;
	int h_setItem_lbl;

	h_work_lbl = m_windowParam.selectPane.pressureLabel.nHeight;
	h_machine_lbl = m_windowParam.selectPane.machineLabel.nHeight;
	h_pressure_lbl = m_windowParam.selectPane.pressureLabel.nHeight;
	h_setItem_lbl = m_windowParam.selectPane.setItemLabel.nHeight;

	h_pressure = m_windowParam.selectPane.pressureList.nItemHeight * 2;
	h_work = setItem_isShown ? (m_windowParam.selectPane.workModeLList.nItemHeight * 3) : ((h - h_pressure_lbl - h_pressure - h_machine_lbl - h_work_lbl) / 2);
	h_machine = setItem_isShown ? (m_windowParam.selectPane.machineList.nItemHeight * 3) : (h - h_pressure_lbl - h_pressure - h_machine_lbl - h_work_lbl - h_work);
	//h_setItem = h - h_pressure - h_work - h_machine;

	// 工作模式
	CRect region_workMode_lbl(left-1, top, right+1, top + h_work_lbl);
	CRect region_workMode(left, region_workMode_lbl.bottom, right, region_workMode_lbl.bottom + h_work);

	if (!m_windowParam.bModeSwitch)
	{
		region_workMode.bottom += h_machine + h_machine_lbl;
	}

	m_lblWorkMode.MoveWindow(&region_workMode_lbl);
	m_workModes.MoveWindow(&region_workMode);

	// 机型选择
	CRect region_machine_lbl(left - 1, region_workMode.bottom, right + 1, region_workMode.bottom + h_machine_lbl);
	CRect region_machine(left, region_machine_lbl.bottom, right, region_machine_lbl.bottom + h_machine);
	if (!m_windowParam.bModeSwitch)
	{
		region_machine_lbl.bottom = region_machine_lbl.bottom - (h_machine + h_machine_lbl);
		region_machine.bottom = region_machine.bottom - (h_machine + h_machine_lbl);
		m_lblMachine.ShowWindow(SW_HIDE);
		m_machine.ShowWindow(SW_HIDE);
	}
	m_lblMachine.MoveWindow(&region_machine_lbl);
	m_machine.MoveWindow(&region_machine);
	// 调压选择
	CRect region_pressure_lbl(left - 1, region_machine.bottom, right + 1, region_machine.bottom + h_pressure_lbl);
	CRect region_pressure(left, region_pressure_lbl.bottom, right, region_pressure_lbl.bottom + h_pressure);
	m_lblPressure.MoveWindow(&region_pressure_lbl);
	m_pressure.MoveWindow(&region_pressure);

	//设定项
	m_lblSetItem.ShowWindow(setItem_isShown ? SW_SHOW : SW_HIDE);
	m_listSetItem.ShowWindow(setItem_isShown ? SW_SHOW : SW_HIDE);
	if (setItem_isShown)
	{
		CRect region_setItem_lbl(left - 1, region_pressure.bottom, right + 1, region_pressure.bottom + h_setItem_lbl);
		CRect region_setItem(left, region_setItem_lbl.bottom, right, bottom);
		m_lblSetItem.MoveWindow(&region_setItem_lbl);
		m_listSetItem.MoveWindow(&region_setItem);
	}
}

BOOL CHsvcsDlg::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}

void CHsvcsDlg::OnLbnSelchangeListWorkMode()
{
	m_threadManager.ResetRunAndStopLogics();

	m_btnStart.EnableWindow(FALSE);
	m_machine.ResetContent();

	int nCursel = m_workModes.GetCurSel();
	if (nCursel < 0)
		return;

	m_uiObjectManager.SetWorkModeVal(nCursel);

	CWorkMode* pWorkMode = m_workModeFactory.GetWorkMode(nCursel);
	int nCount = pWorkMode->GetMachineCount();
	for (int i = 0; i < nCount; i++)
	{
		MODE_MACHINE machine;
		pWorkMode->GetMachine(i, machine);
		LPCWSTR szIdText = (LPCWSTR)machine.szId;
		m_machine.InsertString(-1, szIdText);
	}

	m_machine.SetCurSel(0);
	OnLbnSelchangeListMachine();
}

void CHsvcsDlg::OnLbnSelchangeListMachine()
{
	m_threadManager.ResetRunAndStopLogics();

	// 设置启动按钮的使能状态
	SetStartButtonStatus();
}

// 调压选择改变
void CHsvcsDlg::OnLbnSelchangeListPressure()
{
	// 设置启动按钮的使能状态
	SetStartButtonStatus();
}

// 设置启动按钮的使能状态
void CHsvcsDlg::SetStartButtonStatus()
{
	int nModeCursel = m_workModes.GetCurSel();
	int nMachineCursel = m_machine.GetCurSel();
	int nPressureCursel = m_pressure.GetCurSel();

	m_uiObjectManager.SetWorkModeVal(nModeCursel);
	m_uiObjectManager.SetMachineVal(nMachineCursel);
	m_uiObjectManager.SetPressureSelVal(nPressureCursel);

	m_btnStart.EnableWindow(nModeCursel >= 0 && nMachineCursel >= 0 && nPressureCursel >= 0);
}

// 更新UI显示
void CHsvcsDlg::RefreshUI()
{
	// 获取采集的信号的值
	CMap<CString, LPCWSTR, double, double> mapInputSignalVals;
	CMap<CString, LPCWSTR, double, double> uiSignalVals;
	
	m_dataManager.CopyInputSignalTo(mapInputSignalVals);

	// 更新采集信号UI对象的值
	CString szSignalId;
	double dblVal = 0;

	for (int i = 0; i < m_nCellCtrlCount; i++)
	{
		CHmjCell& cell = m_pCellCtrls[i];
		szSignalId = cell.GetId();
		
		if (mapInputSignalVals.Lookup(szSignalId, dblVal))
		{
			cell.SetValue(dblVal);
			uiSignalVals.SetAt(szSignalId, dblVal);
		}
	}
	
	m_uiObjectManager.SetInputSignalUiVals(uiSignalVals);

	// 用户设定项的值
	CMap<CString, LPCWSTR, double, double> userSetItemVals;
	CString szItemId;
	int nCount = m_listSetItem.GetCount();
	for (int i = 0; i < nCount; i++)
	{
		m_listSetItem.GetVal(i, szItemId, dblVal);
		userSetItemVals.SetAt(szItemId, dblVal);
	}	
	
	m_uiObjectManager.SetUserSetItemVal(userSetItemVals);
}

BOOL CHsvcsDlg::DestroyWindow()
{
	KillTimer(INIT_TIMER_ID);
	KillTimer(REFRESH_TIMER_ID);
	KillTimer(QUIT_TIMER_ID);

	ClearCards();

	m_paneAbort.DestroyWindow();
	m_panePassWord.DestroyWindow();

	POSITION pos = m_dialogMsg.GetStartPosition();
	while (pos)
	{
		DWORD dwMsg = 0;
		CDialogEx* pDialog = NULL;
		m_dialogMsg.GetNextAssoc(pos, dwMsg, pDialog);
		pDialog->DestroyWindow();
		delete pDialog;
	}
	m_dialogMsg.RemoveAll();

	if (m_pBmpLogo)
		delete m_pBmpLogo;
	m_pBmpLogo = NULL;

	if (m_pCellCtrls)
	{
		for (SHORT i = 0; i < m_nCellCtrlCount; i++)
		{
			CHmjCell& cell = m_pCellCtrls[i];
			cell.DestroyWindow();
		}
		delete[] m_pCellCtrls;
	}
	m_pCellCtrls = NULL;

	if (m_pBlankCells)
	{
		for (SHORT i = 0; i < m_nBlankCellCount; i++)
		{
			CHmjCell& cell = m_pBlankCells[i];
			cell.DestroyWindow();
		}
		delete[] m_pBlankCells;
	}
	m_pBlankCells = NULL;

	m_cellCurWorkTime.DestroyWindow();
	m_cellTotalWorkTime.DestroyWindow();

	return CDialogEx::DestroyWindow();
}

// 清理板卡
void CHsvcsDlg::ClearCards()
{
	int nCount = m_logicCards.GetCount();
	for (int i = 0; i < nCount; i++)
	{
		delete m_logicCards[i];
	}

	m_logicCards.RemoveAll();
}

// 设置逻辑加载器参数
// logicConfigLoader:逻辑加载器
void CHsvcsDlg::SetLogicConfigLoaderParam(CLogicConfigLoader& logicConfigLoader)
{
	logicConfigLoader.SetSignalObjectFactory(&m_signalObjectFactory);
	logicConfigLoader.SetParameterFactory(&m_parameterFactory);
	logicConfigLoader.SetLogicTimerManager(&m_logicTimerManager);
	logicConfigLoader.SetLogicCounterManager(&m_logicCounterManager);
	logicConfigLoader.SetStatusTimeManager(&m_statusTimeManager);
	logicConfigLoader.SetActionSignalManager(&m_actionSignalManager);
	logicConfigLoader.SetUiSignalFactory(&m_uiSignalFactory);
	logicConfigLoader.SetUiObjectManager(&m_uiObjectManager);
	logicConfigLoader.SetMainWnd(GetSafeHwnd());
}

// 启动设备
// machine：输入参数，进行参数
void CHsvcsDlg::StartDevice(const MODE_MACHINE& machine)
{
	// 加载逻辑
	CWaitCursor  waitCursor;
	CString szErrMsg;

	m_btnStart.EnableWindow(FALSE);

	m_threadManager.ResetRunAndStopLogics();
	m_logicFactory.ClearRunAndStopLogics();
	
	CLogicConfigLoader logicConfigLoader;
	SetLogicConfigLoaderParam(logicConfigLoader);

	BOOL bRet = logicConfigLoader.LoadRunAndStopLogics(machine.szFileName, m_logicFactory, szErrMsg);
	if (!bRet)
	{
		m_btnStart.EnableWindow();
		MessageBox(szErrMsg, L"加载逻辑", MB_OK | MB_ICONERROR);
		return;
	}

	// 设置运行和停止逻辑
	m_threadManager.SetRunAndStopLogics(m_logicFactory.GetRunLogics(), m_logicFactory.GetStopLogics(), m_logicFactory.GetStopLogicExitTime());

	// 启动设备
	int nMsgRet = MessageBox(machine.szStartInfo, L"启动设备", MB_ICONQUESTION | MB_YESNO);
	if (nMsgRet != IDYES)
	{
		m_btnStart.EnableWindow();
		return;
	}

	// 重新设置控件状态
	m_paneAbort.ShowWindow(SW_HIDE);
	for (int nIndex = 0; nIndex < m_nCellCtrlCount; nIndex++)
	{
		CHmjCell&  cell = m_pCellCtrls[nIndex];
		cell.Alert(FALSE);
	}

	// 启动运行线程
	if (!m_threadManager.StartRunLogicThread(szErrMsg))
	{
		m_btnStart.EnableWindow();
		MessageBox(szErrMsg, L"启动设备", MB_OK | MB_ICONERROR);
		return;
	}

	//开始工作计时
	SetTimer(WORKING_TIMER_ID, 100, NULL);
	m_workStartTimer = CTime::GetCurrentTime();
}

// 点击启动设备按钮
void CHsvcsDlg::OnClickedButtonStart()
{
	if (m_bRunning)
	{
		MessageBox(L"设备正在运行！", L"启动设备", MB_ICONEXCLAMATION);
		return;
	}
		
	int nModeIndex = m_workModes.GetCurSel();
	if (nModeIndex < 0)
	{
		MessageBox(L"请选择工作模式！", L"启动设备", MB_ICONEXCLAMATION);
		return;
	}

	CWorkMode* pWorkMode = m_workModeFactory.GetWorkMode(nModeIndex);

	int nMachineIndex = m_machine.GetCurSel();
	if (nMachineIndex < 0)
	{
		MessageBox(L"请选择机型！", L"启动设备", MB_ICONEXCLAMATION);
		return;
	}

	MODE_MACHINE machine;
	pWorkMode->GetMachine(nMachineIndex, machine);

	int nPressureIndex = m_pressure.GetCurSel();
	if (nPressureIndex < 0)
	{
		MessageBox(L"请选择调压方式！", L"启动设备", MB_ICONEXCLAMATION);
		return;
	}

	// 停止待机线程
	CString szErrMsg;
	if (!m_threadManager.TryStopWaitLogicThread(szErrMsg))
	{
		m_btnStart.EnableWindow();
		MessageBox(szErrMsg, L"停止待机逻辑", MB_OK | MB_ICONERROR);
		return;
	}

	// 启动设备
	StartDevice(machine);
}

// 停止设备按钮
void CHsvcsDlg::OnClickedButtonStop()
{
	if (!m_bRunning)
	{
		return;
	}

	int nRet = MessageBox(L"设备正在运行，确定要停止设备吗？", L"停止设备", MB_ICONQUESTION | MB_YESNO);
	if (nRet != IDYES)
		return;

	//退出运行线程
	CString szErrMsg;
	if (!m_threadManager.TryStopRunLogicThread(szErrMsg))
	{
		MessageBox(szErrMsg, L"停止设备", MB_OK | MB_ICONERROR);
		return;
	}
}

// 关闭设备按钮
void CHsvcsDlg::OnClickedButtonExit()
{
	// "suoping"状态
	if (ReadHeg()==L"1")
	{
	if (MessageBox(_T("确定要关机吗？"), _T("警告"), MB_YESNO) == IDYES)
	{
		if (m_bRunning)
		{
			MessageBox(L"设备正在运转，不能关闭软件！", L"退出", MB_ICONEXCLAMATION | MB_OK);
			return;
		}

		CString szErrMsg;
		if (!m_threadManager.TryStopWorkerThreads(szErrMsg))
		{
			MessageBox(szErrMsg, L"退出", MB_ICONEXCLAMATION | MB_OK);
			return;
		}

		HANDLE hToken;
		TOKEN_PRIVILEGES tkp;
		if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
		{
			MessageBox(_T("关机失败..."), _T("警告"), MB_OK);
			return;
		}
		LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
			&tkp.Privileges[0].Luid);
		tkp.PrivilegeCount = 1;
		tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
		AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, NULL);
		if (GetLastError() != ERROR_SUCCESS)
		{
			MessageBox(_T("关机失败..."), _T("警告"), MB_OK);
			return;
		}
		ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0); //重启只需要把EWX_SHUTDOWN改为EWX_REBOOT
	}
	}
	// “jieping"状态
	else
	{
		if (MessageBox(_T("确定要退出系统吗？"), _T("警告"), MB_YESNO) == IDYES)
		{
			if (m_bRunning)
			{
				MessageBox(L"设备正在运转，不能关闭软件！", L"退出", MB_ICONEXCLAMATION | MB_OK);
				return;
			}

			CString szErrMsg;
			if (!m_threadManager.TryStopWorkerThreads(szErrMsg))
			{
				MessageBox(szErrMsg, L"退出", MB_ICONEXCLAMATION | MB_OK);
				return;
			}

			SetTimer(QUIT_TIMER_ID, 25, NULL);
		}
	}
	
#if 0
	if (m_bRunning)
	{
		MessageBox(L"设备正在运转，不能关闭软件！", L"退出", MB_ICONEXCLAMATION | MB_OK);
		return;
	}

	int nRet = MessageBox(L"确定要关闭软件吗？", L"退出", MB_ICONQUESTION | MB_YESNO);
	if (nRet != IDYES)
		return;

	CString szErrMsg;
	if (!m_threadManager.TryStopWorkerThreads(szErrMsg))
	{
		MessageBox(szErrMsg, L"退出", MB_ICONEXCLAMATION | MB_OK);
		return;
	}

	SetTimer(QUIT_TIMER_ID, 25, NULL);
#endif

}

void CHsvcsDlg::OnClickedButtonOil()
{
	MessageBox(_T("油压检测功能敬请期待..."), _T("提示"), MB_OK);
}

// 处理I/O线程发送的消息
afx_msg LRESULT CHsvcsDlg::OnIoThreadMsg(WPARAM wParam, LPARAM lParam)
{
	MessageBox((LPCWSTR)lParam, L"I/O线程", wParam ? (MB_ICONERROR | MB_OK) : MB_OK);

	return 0;
}



// 处理运行逻辑线程发送的消息
afx_msg LRESULT CHsvcsDlg::OnRunLogicThreadMsg(WPARAM wParam, LPARAM lParam)
{
	MessageBox((LPCWSTR)lParam, L"运行逻辑线程", wParam ? (MB_ICONERROR | MB_OK) : MB_OK);

	return 0;
}

// 处理停止逻辑线程发送的消息
afx_msg LRESULT CHsvcsDlg::OnStopLogicThreadMsg(WPARAM wParam, LPARAM lParam)
{
	MessageBox((LPCWSTR)lParam, L"停止逻辑线程", wParam ? (MB_ICONERROR | MB_OK) : MB_OK);

	return 0;
}

// 工作线程停止的消息
afx_msg LRESULT CHsvcsDlg::OnWorkerThreadStopped(WPARAM wParam, LPARAM lParam)
{
	m_bWorkerThreadRuning = FALSE;

	return 0;
}

// 开始停止逻辑
afx_msg LRESULT CHsvcsDlg::OnDoStopLogic(WPARAM wParam, LPARAM lParam)
{
	CString szErrMsg;

	if (!m_threadManager.StartStopLogicThread(szErrMsg))
	{
		MessageBox(szErrMsg, L"执行停止逻辑", MB_ICONEXCLAMATION);
		return 1;
	}

	//关闭设备运行计时
	KillTimer(WORKING_TIMER_ID);
	CTimeSpan span = CTime::GetCurrentTime() - m_workStartTimer;
	m_totalWorkTime.nHour += span.GetHours();
	m_totalWorkTime.nMinute += span.GetMinutes();
	m_totalWorkTime.nHour += m_totalWorkTime.nMinute / 60;
	m_totalWorkTime.nMinute %= 60;

	CString szTotalWorkTime;
	szTotalWorkTime.Format(L"%d小时%d分钟", m_totalWorkTime.nHour, m_totalWorkTime.nMinute);
	m_cellTotalWorkTime.SetValue(szTotalWorkTime);

	//将新的“全部工作时间”写入parameter.xml
	CParameterConfigLoader  loader;
	//CString szErrMsg;
	loader.SetTotalWorkTime(m_totalWorkTime.nHour, m_totalWorkTime.nMinute, szErrMsg);

	return 0;
}

// UI控件报警消息处理
afx_msg LRESULT CHsvcsDlg::OnUiAlert(WPARAM wParam, LPARAM lParam)
{
	SHORT nIndex = (SHORT)wParam;
	DWORD bAlert = (DWORD)lParam;
	if (nIndex < m_nCellCtrlCount)
	{
		CHmjCell& cell = m_pCellCtrls[nIndex];

		if (bAlert)
		{
			CString szAlertMsg;
			if (m_uiObjectManager.GetAlertMsg(cell.GetId(), szAlertMsg))
			{
				cell.SetAlertMsg(szAlertMsg);
				cell.Alert(TRUE);
			}
		}
		else
		{
			cell.Alert(FALSE);
		}
	}

	return 0;
}


afx_msg LRESULT CHsvcsDlg::OnLogicThreadDialogMsg(WPARAM wParam, LPARAM lParam)
{
	DWORD dwMsg = (DWORD)lParam;
	CDialogEx* pDialog = NULL;
	if (!m_dialogMsg.Lookup(dwMsg, pDialog))
	{
		pDialog = new CMsgPane(dwMsg, this);
		m_dialogMsg.SetAt(dwMsg, pDialog);

		pDialog->Create(IDD_DIALOG_DIALOG);
	}

	pDialog->ShowWindow(SW_SHOW);

	return 0;
}

void CHsvcsDlg::OnMove(int x, int y)
{
	CDialogEx::OnMove(x, y);

	m_paneAbort.Center();
}

LRESULT CHsvcsDlg::OnNcHitTest(CPoint point)
{
	UINT nHitTest = CDialogEx::OnNcHitTest(point);
	if (m_windowParam.bMoveWindow)
	if (nHitTest == HTCLIENT)
	{
		CRect rcTitle;
		GetClientRect(&rcTitle);
		rcTitle.bottom = m_windowParam.titlebar.nHeight;
		CPoint pt = point;
		ScreenToClient(&pt);
		if (rcTitle.PtInRect(pt))
			return HTCAPTION;
	}
	return nHitTest;
}

BOOL CHsvcsDlg::PreTranslateMessage(MSG* pMsg)
{
	m_listSetItem.CheckEditStatus(pMsg);

	if (pMsg->message == WM_LBUTTONDOWN)
	{
		m_bLock = TRUE;
	}

	if (pMsg->message == WM_LBUTTONDOWN)
	{
		m_bLock = FALSE;
	}

	if (pMsg->message == WM_KEYDOWN)
	{
		if (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN)
		{
			return TRUE;
		}
		if (GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_MENU) && GetAsyncKeyState(VK_SHIFT) && m_bLock)
		{
			m_bLock = FALSE;
			SetTimer(119, 10, NULL);
			
		}
	}
	else if (pMsg->message == WM_SYSKEYDOWN)
	{
		
	}

	return CDialogEx::PreTranslateMessage(pMsg);
}

// 根据运行状态设置控件的使能状态
void CHsvcsDlg::EnableCtrlsByRuning()
{
	m_btnStart.EnableWindow(!m_bRunning);
	m_btnStop.EnableWindow(m_bRunning);
	m_btnExit.EnableWindow(!m_bRunning);
	m_workModes.EnableWindow(!m_bRunning);
	m_machine.EnableWindow(!m_bRunning);
	m_pressure.EnableWindow(!m_bRunning);
}

// 处理逻辑线程正在运行的消息
afx_msg LRESULT CHsvcsDlg::OnLogicThreadRunning(WPARAM wParam, LPARAM lParam)
{
	m_bRunning = (wParam > 1);
	if (wParam >= 1)
		m_bWorkerThreadRuning = TRUE;

	if (m_bAbort)
	{
		SetCtrlStatusByAbort();
	}
	else
	{
		EnableCtrlsByRuning();		
	}

	m_lblRunStatus.SetStatus(wParam);

	return 0;
}

// 启动待机线程
afx_msg LRESULT CHsvcsDlg::OnStartWaitThread(WPARAM wParam, LPARAM lParam)
{	
	// 运行逻辑和停止逻辑归零
	m_threadManager.SetRunAndStopLogics(NULL, NULL, -1);
	// 按钮状态
	m_bRunning = FALSE;

	// 启动待机逻辑
	if (!m_bAbort)
	{
		EnableCtrlsByRuning();
		StartWaitLogic();
	}
	else
	{
		m_lblRunStatus.SetStatus(0);
		SetCtrlStatusByAbort();
	}

	return 0;
}

afx_msg LRESULT CHsvcsDlg::OnLogicThreadAbortMsg(WPARAM wParam, LPARAM lParam)
{
	m_paneAbort.AddMsg((DWORD)lParam);

	m_bAbort = TRUE;

	SetCtrlStatusByAbort();

	return 0;
}

void CHsvcsDlg::SetCtrlStatusByAbort()
{
	m_btnStart.EnableWindow(FALSE);
	m_btnStop.EnableWindow(TRUE);
	m_btnExit.EnableWindow(TRUE);
	m_workModes.EnableWindow(FALSE);
	m_machine.EnableWindow(FALSE);
	m_pressure.EnableWindow(FALSE);
	m_listSetItem.EnableWindow(FALSE);
}

// 启动待机逻辑
BOOL CHsvcsDlg::StartWaitLogic()
{
	m_lblRunStatus.SetStatus(0);

	// 加载待机线程
	CWaitCursor  waitCursor;
	CString szErrMsg;

	m_threadManager.ResetWaitLogics();
	m_logicFactory.ClearWaitLogics();

	CLogicConfigLoader logicConfigLoader;
	SetLogicConfigLoaderParam(logicConfigLoader);

	BOOL bRet = logicConfigLoader.LoadWaitLogics(m_logicFactory, szErrMsg);
	if (!bRet)
	{
		MessageBox(szErrMsg, L"加载待机逻辑", MB_OK | MB_ICONERROR);
		return FALSE;
	}

	// 设置待机逻辑
	m_threadManager.SetWaitLogics(m_logicFactory.GetWaitLogics());

	// 启动待机线程	
	bRet = m_threadManager.StartWaitLogicThread(szErrMsg);
	if (!bRet)
		MessageBox(szErrMsg, L"启动待机逻辑", MB_OK | MB_ICONEXCLAMATION);
	else
		m_lblRunStatus.SetStatus(1);

	return bRet;
}

void CHsvcsDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_bLock = TRUE;

	CDialogEx::OnLButtonDown(nFlags, point);
}


void CHsvcsDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
	m_bLock = FALSE;

	CDialogEx::OnLButtonUp(nFlags, point);
}


void CHsvcsDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	m_bLock = TRUE;

	CDialogEx::OnLButtonDblClk(nFlags, point);
}
